﻿using IOA.MES.Client.Common;
using IOA.MES.Client.Models.Response;
using IOA.MES.Client.Settings;
using IOA.MES.Common;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
using System.Reflection;
using System.Net;
using IOA.MES.Client.Models;
using Newtonsoft.Json;
using System.Text;

namespace IOA.MES.Client.EL2
{
    /// <summary>
    /// EL2Index.xaml 的交互逻辑
    /// </summary>
    public partial class EL2Index : Window
    {
        private static bool isExcute = false;
        private static HttpListener listener = new HttpListener();
        private List<string> qLevels = new List<string>();
        private List<ViaSiteRecord> _records { get; set; } = new List<ViaSiteRecord>();
        private List<KeyValuePair<int, string>> fileChanges { get; set; } = new List<KeyValuePair<int, string>>();

        public EL2Index()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(BaseEnv.UserInfo.FtpConfig?.FtpRoot) || string.IsNullOrWhiteSpace(BaseEnv.UserInfo.FtpConfig?.UserName) || string.IsNullOrWhiteSpace(BaseEnv.UserInfo.FtpConfig?.Password))
            {
                CommonMessage.Alert(this, "请配置文件上传地址\r\nPlease configure the file upload address", false);
            }

            txtTrueName.Text = BaseEnv.UserInfo.TrueName;

            InitDuties();
            InitMachines();
            InitQLevels();
            InitRecords();

            StartHttpListen();
        }


        #region 初始化数据
        public void InitDuties()
        {
            var duties = BaseEnv.InvokeApi<QueryDutiesResponse>("/api/Auth/QueryDuties", new { WorkshopCode = BaseEnv.WorkshopCode }).Data.Duties;

            cbDuties.ItemsSource = duties;
            cbDuties.DisplayMemberPath = "DutyName";
            cbDuties.SelectedValuePath = "DutyId";

            if (duties.Any())
            {
                cbDuties.SelectedIndex = 0;
            }
        }

        public void InitMachines()
        {
            var machines = BaseEnv.InvokeApi<QueryMachinesResponse>("/api/Machine/QueryMachines", new { WorkshopCode = BaseEnv.WorkshopCode, MachineType = (int)MachineType.EL2 }).Data.Machines;
            cbMachines.ItemsSource = machines;
            cbMachines.DisplayMemberPath = "MachineName";
            cbMachines.SelectedValuePath = "MachineId";

            if (machines.Any(_ => _.MachineId == BaseEnv.MachineId))
            {
                cbMachines.SelectedIndex = machines.FindIndex(_ => _.MachineId == BaseEnv.MachineId);
            }
            else
            {
                CommonMessage.Alert(this, "Vui lòng chọn lại thiết bị trong cài đặt hệ thống ngay bây giờ\r\n请先在系统设置中重新选择设备\r\nPlease reselect the device in the system settings now"); ;
                new SettingsIndex().ShowDialog();
            }
        }

        private void InitRecords()
        {
            new TaskFactory().StartNew(() =>
            {
                Thread.Sleep(100);
                Dispatcher.Invoke(new Action(() =>
                {
                    var response = BaseEnv.InvokeApi<QueryViaSiteRecordsResponse>("/api/Machine/QueryViaSiteRecords", new { DutyId = Convert.ToInt32(cbDuties.SelectedValue), SiteType = SiteType.EL2, MachineId = Convert.ToInt32(cbMachines.SelectedValue) });
                    if (response.ErrCode != 200)
                    {
                        CommonMessage.Alert(this, response.ErrMsg);
                        return;
                    }
                    _records.Clear();
                    _records.AddRange(response.Data.Records);
                    _records.ForEach(_ => _.No = _records.Count - _records.IndexOf(_));
                    BindGridRecords();
                }));
            });
        }

        private void BindGridFileChanges(string content)
        {
            fileChanges.Insert(0, new KeyValuePair<int, string>(fileChanges.Count + 1, content));
            gridFileChanges.ItemsSource = null;
            gridFileChanges.ItemsSource = fileChanges;
        }

        private void BindGridRecords()
        {
            gridRecords.ItemsSource = null;
            gridRecords.ItemsSource = _records;
            lbTotal.Content = _records.Select(_ => _.Code.ToUpper().Trim()).Distinct().Count();
        }

        public void InitQLevels()
        {
            qLevels = BaseEnv.InvokeApi<QueryQLevelsResponse>("/api/NQC/QueryLevels", new { }).Data.Levels;
            if (qLevels.Count < 2)
            {
                CommonMessage.Alert(this, "Hệ thống cần được cấu hình với ít nhất hai cấp độ phán đoán trở lên, vui lòng liên hệ với nhân viên kỹ thuật\r\n系统需要至少配置2个以上判定等级，请联系工艺人员\r\nThe system needs to be configured with at least two or more judgment levels, please contact the technical staff");
                Environment.Exit(0);
            }
        }
        private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            InitRecords();
        }

        /// <summary>
        /// 启动Http监听
        /// </summary>
        private void StartHttpListen()
        {
            new TaskFactory().StartNew(() =>
            {
                ExcuteHttp();
            });
        }
        #endregion

        /// <summary>
        /// 启动Http监听
        /// </summary>
        private void ExcuteHttp()
        {
            listener.Prefixes.Clear();
            var httpRoot = BaseEnv.GetStorage("El2HttpRoot");
            httpRoot = !string.IsNullOrWhiteSpace(httpRoot) ? httpRoot : "http://127.0.0.1:1000/";
            listener.Prefixes.Add(httpRoot);
            listener.Start();
            isExcute = true;
            CommonMessage.Log(LogLevel.Warn, $"Http服务已启动（{httpRoot}）");
            while (isExcute)
            {
                try
                {
                    HttpListenerContext context = null;
                    try
                    {
                        context = listener.GetContext();
                    }
                    catch (Exception ex)
                    {
                        if (!isExcute)
                        {
                            return;
                        }

                        isExcute = false;
                        CommonMessage.Alert(this, $"Http服务已停止（{httpRoot}），请重新启动MES软件", true, ex);
                        return;
                    }

                    HttpListenerRequest request = context.Request;
                    var responseStr = string.Empty;
                    try
                    {
                        if (!string.Equals(request.HttpMethod, "POST", StringComparison.CurrentCultureIgnoreCase))
                        {
                            responseStr = JsonConvert.SerializeObject(new
                            {
                                Code = 400,
                                Message = "接口不支持GET请求",
                                HasError = true
                            });
                        }
                        else
                        {
                            var reader = new StreamReader(request.InputStream);
                            var bodyStr = reader.ReadToEnd();
                            CommonMessage.Log(LogLevel.Warn, $"接收到请求：\r\n{bodyStr}");
                            responseStr = JsonConvert.SerializeObject(new
                            {
                                Code = 0,
                                Message = "请求成功",
                                HasError = false
                            });
                            if (string.Equals(request.RawUrl, "/UploadResult", StringComparison.CurrentCultureIgnoreCase))
                            {
                                Dispatcher.Invoke(new Action(() =>
                                {
                                    UploadResult(bodyStr);
                                }));
                            }
                            else
                            {
                                responseStr = JsonConvert.SerializeObject(new
                                {
                                    Code = 403,
                                    Message = "请求地址无效",
                                    HasError = true
                                });
                            }
                            CommonMessage.Log(LogLevel.Warn, $"请求处理成功");
                        }
                    }
                    catch (Exception ex)
                    {
                        CommonMessage.Log(LogLevel.Fatal, "请求处理异常", ex);
                        responseStr = JsonConvert.SerializeObject(new
                        {
                            Code = 500,
                            Message = ex.Message,
                            HasError = true
                        });
                    }
                    CommonMessage.Log(LogLevel.Warn, $"返回请求：\r\n{responseStr}");

                    byte[] buffer = Encoding.UTF8.GetBytes(responseStr);
                    context.Response.ContentLength64 = buffer.Length;
                    context.Response.StatusCode = 200;
                    context.Response.ContentType = "application/json";
                    using (Stream output = context.Response.OutputStream)
                    {
                        output.Write(buffer, 0, buffer.Length);
                    }
                }
                catch (Exception ex)
                {
                    CommonMessage.Log(LogLevel.Fatal, "请求监听异常", ex);
                }
            }
        }

        /// <summary>
        /// 获取组件信息
        /// </summary>
        private Component GetComponent(string barCode)
        {
            var getComponentResponse = BaseEnv.InvokeApi<GetComponentResponse>("/api/Machine/GetComponent", new { BarCode = barCode });
            if (getComponentResponse.ErrCode != 200)
            {
                mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                mediaElResult.Play();
                throw new Exception(getComponentResponse.ErrMsg);
            }
            else if (getComponentResponse.Data == null || getComponentResponse.Data.Component == null)
            {
                mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                mediaElResult.Play();
                throw new Exception($"组件不存在\r\nComponent does not exist：\r\n{barCode}");
            }

            return getComponentResponse.Data.Component;
        }

        /// <summary>
        /// 上传EL结果
        /// </summary>
        private void UploadResult(string bodyStr)
        {
            var body = JsonConvert.DeserializeObject<ElResultRequest>(bodyStr);
            if (string.IsNullOrWhiteSpace(body.LotNumber))
            {
                throw new Exception("组件条码为空");
            }

            Thread.Sleep(3000);
            var elResult = new List<ElResult>();
            var component = GetComponent(body.LotNumber);
            //上传EL图片
            try
            {
                var ftpUtils = new FtpUtils(BaseEnv.UserInfo.FtpConfig.FtpRoot, BaseEnv.UserInfo.FtpConfig.UserName, BaseEnv.UserInfo.FtpConfig.Password);
                var elDirectory = $"/{BaseEnv.WorkshopCode}/el2/{component.WorkOrderNo}";
                ftpUtils.CheckAndCreateDirectory(elDirectory);
                var elFileName = $"{elDirectory}/{Path.GetFileName(body.ELImageFilePath)}";
                ftpUtils.Upload(File.ReadAllBytes(body.ELImageFilePath), elFileName);
                BindGridFileChanges($"图片上传完成：{body.ELImageFilePath}");
                elResult.Add(new ElResult
                {
                    Image = $"{BaseEnv.UserInfo.FtpConfig.FtpRoot}{elFileName}",
                    Positions = (body.ELTestResults ?? new List<ELResultItem>())
                        .Where(p => !string.Equals(p.Name, "OK", StringComparison.CurrentCultureIgnoreCase))
                        .Select(_ => new ElPosition
                        {
                            Name = _.Name,
                            Position = _.Position
                        }).ToList()
                });
            }
            catch (Exception ex)
            {
                throw new Exception($"EL图片上传失败：{ex.Message}");
            }

            ViaSite(body.LotNumber, body.IsOK, elResult);
        }

        /// <summary>
        /// 过站
        /// </summary>
        private void ViaSite(string barCode, bool result, List<ElResult> elResult)
        {
            CommonMessage.Log(LogLevel.Info, $"条码：{txtCode.Text.Trim()}，结果：{result}，图片：{JsonConvert.SerializeObject(elResult)}");

            txtCode.Text = barCode;
            var viaSiteRequest = new
            {
                SiteType = (int)SiteType.EL2,
                DutyId = Convert.ToInt32(cbDuties.SelectedValue),
                MachineId = Convert.ToInt32(cbMachines.SelectedValue),
                Code = barCode,
                QLevel = result ? qLevels[0] : qLevels[1],
                ElResults = elResult,
            };

            var response = BaseEnv.InvokeApi<ViaSiteResponse>("/api/Machine/ViaSite", viaSiteRequest);
            if (response.ErrCode != 200)
            {
                mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                mediaElResult.Play();
                CommonMessage.Alert(this, response.ErrMsg, false);
                return;
            }

            mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Success.wav");
            mediaElResult.Play();

            CommonMessage.Log(LogLevel.Info, $"过站成功：{txtCode.Text.Trim()}");

            if (response.Data.DutyId != Convert.ToInt32(cbDuties.SelectedValue))
            {
                cbDuties.SelectedValue = response.Data.DutyId;
            }
            else
            {
                response.Data.ViaSiteRecord.No = _records.Count + 1;
                _records.Insert(0, response.Data.ViaSiteRecord);
                BindGridRecords();
            }
        }

        private void Menu_Click(object sender, RoutedEventArgs e)
        {
            switch (((MenuItem)sender).Name)
            {
                case "btnSettings":
                    new SettingsIndex().ShowDialog();
                    break;
                case "btnDeviceSettings":
                    if (new WinElSettings().ShowDialog() == true)
                    {
                        StartHttpListen();
                    }
                    break;
                case "btnMissingRecords":
                    new MissingSiteRecord(Convert.ToInt32(cbMachines.SelectedValue)).Show();
                    break;
                case "btnScanEl2":
                    new WinPassEL2().Show();
                    break;
                case "btnLogout":
                    new LoginWindow(false).Show();
                    this.Hide();
                    break;
                case "btnAbout":
                    MessageBox.Show($"AISUNMes Product Version:{FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion}");
                    break;
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if (listener != null)
            {
                isExcute = false;
                listener.Close();
            }
            Environment.Exit(0);
        }
    }
}
